<template>
  <div
    ref="cellEditor"
    class="cell-editor-box"
    :class="{ 'ele-focus': isSelected }"
    @click.stop="onEditorClick"
  >
    <a-icon class="add-btn" type="plus" @click="addCodeCell('before')" />
    <div class="editor-content">
      <div class="output_wrapper">
        <div v-show="showCodeBox" class="code-box">
          <code-mirror-editor
            class="code-mirror"
            :value="value"
            :theme="theme"
            :mode="mode"
            :height="height"
            from="operator"
            :table-list="_linkedTableList"
            @update:value="updateValue"
            @cm:click="onEditorClick"
            @cm:focus="onCmfocus"
            @cm:blur="onCmblur"
          ></code-mirror-editor>
          <div class="cell-status">
            {{ cellStatus }}
          </div>
          <div class="btn-box" @click="runCodeCell">
            <a-icon-font type="iconyunhang" />
          </div>
        </div>
        <!-- <div
          v-show="!showCodeBox"
          class="output_collapsed"
          title="click to expand source code"
          @click="showCodeBox = !showCodeBox"
        >
          . . .
        </div> -->
      </div>
      <pre
        v-if="runOutput"
        class="result-box"
        :class="{ error: resultType === 'error' }"
        v-html="runOutput"
      ></pre>

      <div class="editor-menu">
        <a-dropdown :trigger="['click']" :overlay-style="{ zIndex: 1051 }">
          <a-icon-font
            type="icondiandian"
            title="drag cell or open menu"
            style="cursor: pointer; font-size: 18px;"
          />
          <a-menu slot="overlay">
            <a-menu-item key="copy" @click="copyCell">
              复制
            </a-menu-item>
            <a-menu-item v-if="canDelete" key="cut" @click="cutCell">
              剪切
            </a-menu-item>
            <a-menu-item key="paste" @click="pasteCell">
              粘贴
            </a-menu-item>
            <a-menu-item
              v-if="showCodeBox && runOutput"
              key="hideEditor"
              @click="showCodeBox = !showCodeBox"
            >
              隐藏编辑区
            </a-menu-item>
            <a-menu-item
              v-if="!showCodeBox"
              key="expandEditor"
              @click="showCodeBox = !showCodeBox"
            >
              展开编辑区
            </a-menu-item>
            <a-menu-divider />
            <a-menu-item v-if="canDelete" key="delete" @click="deleteCell">
              删除
            </a-menu-item>
          </a-menu>
        </a-dropdown>
      </div>
      <div
        class="out_prompt_overlay"
        title="try to drag the cell"
        draggable="true"
        @dragstart="(event) => $emit('drag-start', event)"
        @dragenter="(event) => $emit('drag-enter', event)"
        @dragend="(event) => $emit('drag-end')"
      ></div>
    </div>
    <a-icon
      class="add-btn add-btn-layout"
      type="plus"
      @click="addCodeCell('after')"
    />
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import CodeMirrorEditor from '@/components/studio/data/popup/CodeMirrorEditor.vue'
import { Marked } from '@ts-stack/markdown'
import DataStore from '@/store/modules/dataview'

@Component({
  components: {
    CodeMirrorEditor,
  },
})
export default class CodeCellEditor extends Vue {
  //  编辑器代码语言
  @Prop({
    type: String,
    default() {
      return 'python'
    },
  })
  mode!: string

  //  该cell 是否可删除
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  canDelete!: boolean

  //  编辑器主题
  @Prop({
    type: String,
    default() {
      return 'yonce'
    },
  })
  theme!: string

  /** 编辑器高 */
  @Prop({
    type: String,
    default() {
      return 'auto'
    },
  })
  height!: String

  //  编辑器代码
  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  value!: string

  // 编译结果信息
  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  result?: string

  //  结果的类型 error
  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  resultType?: string

  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  paraId!: string

  @Prop({
    type: Number,
    default() {
      return 0
    },
  })
  dataNodeId!: number

  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  selectedCell!: string

  // cell的运行状态
  @Prop({
    type: String,
    default() {
      return '未运行'
    },
  })
  cellStatus!: string

  @Watch('result', { immediate: true, deep: true })
  setOutput(value: any) {
    this.runOutput = value
  }

  @Watch('cellStatus', { immediate: true, deep: true })
  setCellStatus(value: any) {
    if (value !== undefined) {
      this.cellStatus = value
    }
  }

  //  首次载入代码块，若为md 文本块，则自动执行出结果, 并隐藏代码块
  @Watch('value', { immediate: true, deep: true })
  initMdOutput() {
    // if(this.value.length === 0) { //  create a new empty cell
    //   this.firstRender = false
    // }
    if (
      this.value.startsWith('md `') &&
      this.value.endsWith('`') &&
      this.firstRender
    ) {
      this.runCodeCell()
      this.$nextTick(() => {
        this.showCodeBox = false
      })
    }
    this.firstRender = false
  }

  public runOutput: string = ''
  public copyCellValue: string = ''
  public showCodeBox: boolean = true
  public firstRender: boolean = true

  public addCodeCell(config: string) {
    this.$emit('add-cell', config)
  }

  public get _linkedTableList(): any {
    return DataStore.LinkedTableList
  }
  //  是否被选中
  private get isSelected() {
    return this.selectedCell === this.paraId
  }
  //  cm focus触发
  public onCmfocus() {
    this.$emit('editor-focus')
  }
  //  cm blur触发
  public onCmblur() {
    this.$emit('editor-blur')
  }

  public onEditorClick() {
    this.$emit('editor-click')
  }

  //  更新cell代码的值
  public updateValue(value: string) {
    this.$emit('update-value', value)
  }
  //  删除cell
  public deleteCell() {
    this.$emit('delete-cell')
  }
  //  复制cell
  public copyCell() {
    DataStore.setCopiedCellValue(this.value)
  }
  //  剪切cell
  public cutCell() {
    this.copyCell()
    this.deleteCell()
  }
  //  粘贴cell
  public pasteCell() {
    const value = DataStore.CopiedCellValue
    this.$emit('paste-cell', this.dataNodeId, value, this.value)
  }

  //  运行cell 如果是md 语句，直接执行，如果是其他语句，后端api返回结果
  public runCodeCell() {
    if (this.value.startsWith('md `') && this.value.endsWith('`')) {
      //  设置cell的运行状态为运行中
      this.$emit('set-cell-status-running')
      const matchString = this.value.slice(4, this.value.length - 1)
      this.runOutput = Marked.parse(matchString)
      //  设置cell的运行状态为运行完成
      this.$emit('set-cell-status-finished')
    } else {
      this.$emit('run-code-cell')
    }
  }
}
</script>

<style lang="less" scoped>
.cell-editor-box {
  position: relative;

  &:nth-of-type(n + 2) {
    margin-top: -22px;
  }

  &:hover {
    .editor-content {
      border: 1px solid #f5f5f5;
      border-left: 3px solid #5561ff;
    }

    .add-btn,
    .editor-menu {
      visibility: visible;
    }
  }

  .add-btn {
    left: 35px;
    margin-bottom: 5px;
    position: relative;
    visibility: hidden;
  }

  .add-btn-layout {
    z-index: 10;
  }

  .editor-content {
    border: 1px solid #fff;
    border-left: 3px solid #fff;
    box-sizing: border-box;
    padding: 5px;
    padding-left: 0;
  }
}

.ele-focus.cell-editor-box {
  .editor-content {
    border: 1px solid #f5f5f5;
    border-left: 3px solid #5561ff;
  }

  .add-btn,
  .editor-menu {
    visibility: visible;
  }
}

.code-mirror {
  border-left: solid 1px #000;
  margin-left: 31px;
}

.editor-menu {
  align-items: center;
  display: flex;
  height: 28px;
  justify-content: center;
  left: 5px;
  position: absolute;
  top: 32px;
  visibility: hidden;
  width: 28px;

  &:hover {
    background-color: #eeeffd;

    .anticon {
      color: #6973ff;
    }
  }
}

.code-box {
  position: relative;

  .btn-box {
    cursor: pointer;
    position: absolute;
    right: 7px;
    top: 5px;
    z-index: 10;
  }

  .cell-status {
    position: absolute;
    right: 30px;
    top: 5px;
    z-index: 10;
  }
}

.result-box {
  border-left: 1px solid #000;
  line-height: 1;
  margin-bottom: 0;
  margin-left: 31px;
  min-height: 29px;
  padding-left: 5px;
  white-space: pre-wrap;
}

.result-box.error {
  border-left: 2px solid #f00;
}

.error {
  color: #f00;
}

.output_wrapper {
  // cursor: move;
  position: relative;
}

.output_wrapper.grabbing {
  pointer-events: none;
}

.out_prompt_overlay {
  border-radius: 2px;
  cursor: move;
  height: calc(100% - 85px);
  position: absolute;
  top: 55px;
  width: 2%;
  z-index: 10;

  // &:hover {
  //   background-color: #f5f5f5;
  // }
}

.out_prompt_overlay.grabbing {
  cursor: grabbing;
}

.output_collapsed {
  background-color: #fff;
  border: 1px solid transparent;
  border-color: #ccc;
  border-radius: 2px;
  color: #333;
  cursor: pointer;
  text-align: center;

  &:hover {
    background-color: #f5f5f5;
  }
}
</style>
